package emediashared.model;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.runtime.IProgressMonitor;

import emediashared.SharedActivator;
import emediashared.ui.PreferencesDialog;
import emediashared.ui.RemoteNode;

public class SharedHttpClient implements ISharedClient {
	private String url;
	private String name;
	private List<RemoteNode> children;
	private String[] repoLocations;

	public SharedHttpClient(String url, String name, String repos) {
		resetConfiguration(url, name, repos);
	}

	public List<IRemoteFile> getFiles(String parent) throws RemoteException {
		List<IRemoteFile> files = new ArrayList<IRemoteFile>();
		HttpURLConnection connection = null;
		try {
			String query = "?file=" + URLEncoder.encode(parent, "UTF-8");
			String baseUrl = url + query;
			URL queryUrl = new URL(baseUrl);
			connection = (HttpURLConnection) queryUrl.openConnection();
			connection.connect();
			InputStreamReader inStream = new InputStreamReader(connection.getInputStream());
			BufferedReader buff = null;
			try {
				buff = new BufferedReader(inStream);
				while (true) {
					String nextLine = buff.readLine();
					if (nextLine != null) {
						String[] split = nextLine.split("=");
						IRemoteFile remoteFile = new RemoteFile(split[0], Boolean.valueOf(split[1]));
						files.add(remoteFile);
					} else {
						break;
					}
				}
			} finally {
				if (buff != null) {
					buff.close();
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (connection != null) {
				connection.disconnect();
			}
		}

		return files;
	}

	public boolean downloadFile(String sourceFile, String target, IProgressMonitor monitor) throws Exception {
		String remoteLocation = PreferencesDialog.getRemotePath();
		String userName = PreferencesDialog.getUserName();
		File remoteTempDir = new File(remoteLocation, userName);
		remoteTempDir.mkdirs();
		HttpURLConnection connection = null;
		try {
			String query = "?file=" + URLEncoder.encode(sourceFile, "UTF-8") + "&download=true" + "&shared=" + URLEncoder.encode(remoteTempDir.getAbsolutePath(), "UTF-8");
			String baseUrl = url + query;
			URL queryUrl = new URL(baseUrl);
			connection = (HttpURLConnection) queryUrl.openConnection();
			connection.connect();
			InputStreamReader inStream = new InputStreamReader(connection.getInputStream());
			BufferedReader buff = null;
			try {
				buff = new BufferedReader(inStream);
				while (true) {
					String nextLine = buff.readLine();
					if (nextLine == null) {
						break;
					}
					if (nextLine.equals("Failed")) {
						throw new Exception("Failed to download from Url:" + queryUrl + "\n Reason:" + buff.readLine());
					} else {
						File tempFile = new File(nextLine);
						if (tempFile.exists()) {
							try {
								RemoteFile.copy(tempFile.getAbsolutePath(), target, getWrapperMonitor(monitor));
								return true;
							} finally {
								tempFile.delete();
							}
						}
					}
				}
				throw new Exception("Failed to download from Url:" + queryUrl + "\n");
			} finally {
				if (buff != null) {
					buff.close();
				}
			}
		}  finally {
			connection.disconnect();
		}
	}

	private IRemoteProgressMonitor getWrapperMonitor(final IProgressMonitor monitor) throws RemoteException {
		return new RemoteProgressMonitor() {
			private static final long serialVersionUID = 1L;

			@Override
			public void worked(int work) throws RemoteException {
				monitor.worked(work);
			}

			@Override
			public void done() throws RemoteException {
				monitor.done();
			}

			@Override
			public void beginTask(String name, int totalWork) throws RemoteException {
				monitor.beginTask(name, totalWork);
			}
		};
	}

	@Override
	public void resetConfiguration(String url, String name, String repos) {
		this.url = "http://" + url + "/shared.folder.explorer/SharedRepositoryServlet";
		this.name = name;
		repoLocations = repos.split(SharedConstants.PATH_DELIMITTER);
	}

	@Override
	public boolean connect() {
		return false;
	}

	@Override
	public void reConnect() {
		children = null;
	}

	@Override
	public boolean isConnected() {
		return true;
	}

	@Override
	public String getName() {
		return name;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see emediashared.model.ISharedClient#getChildren()
	 */
	@Override
	public List<RemoteNode> getChildren() {
		if (children == null) {
			children = new ArrayList<RemoteNode>();
			try {
				for (String path : repoLocations) {
					children.add(new RemoteNode(new RemoteFile(path, true), null));
				}
			} catch (RemoteException e) {
				children = null;
				SharedActivator.showAndLogError(e);
			}
		}
		return children;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see emediashared.model.ISharedClient#isLoaded()
	 */
	@Override
	public boolean isLoaded() {
		return children != null;
	}

}
